<template>
    <div>
        <slot :code="code" :message="message" :response="response" :loading="loading" :reload="reload"></slot>
    </div>
</template>


<script setup lang="ts">
/* eslint-disable */
import setting from "@/widget/provider/setting";
import {ref, watch} from "vue";

/**
 * 后台请求骨架
 *
 * 简单地说，就是组件版的 ajax 请求，
 *
 * 做数据展示界面的时候，这个组件会非常好用：
 *
 *  1、可以根据当前 API，提前设计好 404、500 等服务降级界面；
 *  2、可以很好地对接骨架屏的设计，有些时候可以省去 js 部分的所有代码。
 */
interface Props {
    // 请求 URL
    url: string;
    // 请求方法
    method?: RequestMethod;
    // 请求头配置
    headers?: Record<string, string>;
    /** 查询条件，带联动效果 */
    where?: Record<string, any>
    // 是否自动加载数据
    autoLoad?: boolean;
    // 数据查询执行器函数
    provider?: (config: any) => Promise<any>;
    // 查询结果格式转换
    resultParser?: (org: any) => any;
}

// 使用 withDefaults 设置默认值
const props = withDefaults(defineProps<Props>(), {
    method: 'GET',
    autoLoad: true,
    headers: {},
    provider: setting.ajax
})

// 是否正在载入数据，如果需要制作骨架屏，或者局部加载条，这个属性很好用
const loading = ref(false);
// 业务结果码，绘制错误界面即可，如果 http 请求出错，全局有个错误弹窗，这里不需要处理
const code = ref(0);
// 异常消息
const message = ref('');
// 响应数据数据
const response = ref();

/**
 * 重新载入数据
 */
const reload = () => {
    if (loading.value) {
        return;
    }

    loading.value = true;

    // ajax 配置
    let params = props.params;
    let setting = {
        url: props.url,
        method: props.method,
        headers: props.headers,
        loading: false
    };

    if (props.type === 'default') {
        setting.params = params;
    } else {
        setting.data = params;
    }

    props.provider(setting).then((ret) => {
        code.value = 0;
        message.value = undefined;
        if (props.resultParser) {
            response.value = props.resultParser(ret);
        } else {
            response.value = ret;
        }
    }).catch(err => {
        code.value = 500;
        message.value = '网络或其他异常!';
        response.value = undefined;
    }).finally(() => {
        loading.value = false;
    })
}

watch(() => props.params, () => {
    reload();
});

// 组件初始化
{
    if (props.autoLoad) {
        reload();
    }
}
</script>
